﻿using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace GDI
{
    public partial class EllipseControl : Control
    {
        /* ------------------------------------------------------------------------------------------ */

        private const int c_HtTransparent = -1;
        private const int c_WmNcHitTest = 0x0084;

        /* ------------------------------------------------------------------------------------------ */

        private RectangleF f_Rect;
        private Pen f_Pen = new Pen(Color.Blue, 2);
        private Brush f_FeelBrush;
        private SmoothingMode f_SmoothingMode = SmoothingMode.Default;
        private float f_Opaque = 1;

        /* ------------------------------------------------------------------------------------------ */

        protected override CreateParams CreateParams
        {
            get
            {
                var P = base.CreateParams;
                P.ExStyle |= (int)(WindowStylesEx.WS_EX_TRANSPARENT);
                //| WindowStylesEx.WS_EX_COMPOSITED);
                return P;
            }
        }

        [DefaultValue(false)]
        public bool MouseTransparent { get; set; }

        [Bindable(false), Browsable(false)]
        public Brush FeelBrush { get { return f_FeelBrush; } set { f_FeelBrush = value; } }

        [Bindable(false), Browsable(false)]
        public Pen Pen { get { return f_Pen; } set { f_Pen = value; } }

        [Bindable(false), Browsable(false)]
        public RectangleF Rect { get { return f_Rect; } set { f_Rect = value; } }

        public Color LineColor
        {
            get { return f_Pen.Color; }
            set
            {
                f_Pen.Color = value;
                Invalidate();
            }
        }

        public float LineWidth
        {
            get { return f_Pen.Width; }
            set
            {
                f_Pen.Width = value;
                Invalidate();
            }
        }

        public SmoothingMode Smoothing { get { return f_SmoothingMode; } set { f_SmoothingMode = value; Invalidate(); } }

        public float Opaque
        {
            get { return f_Opaque; }
            set
            {
                if(Math.Abs(value - f_Opaque) < float.Epsilon) return;
                if(value < 0) value = 0;
                if(value > 1) value = 1;
                f_Opaque = value;
                Invalidate();
            }
        }

        /* ------------------------------------------------------------------------------------------ */

        public EllipseControl()
        {
            SetStyle(
                ControlStyles.UserPaint |
                ControlStyles.Opaque |
                //ControlStyles.DoubleBuffer |
                //ControlStyles.OptimizedDoubleBuffer |
                ControlStyles.ResizeRedraw |
                ControlStyles.AllPaintingInWmPaint |
                ControlStyles.SupportsTransparentBackColor,
                true);

            //SetStyle(ControlStyles.OptimizedDoubleBuffer, false);
            InitializeComponent();
        }

        /* ------------------------------------------------------------------------------------------ */

        protected override void OnCreateControl()
        {
            //DoubleBuffered = true;
            base.OnCreateControl();
        }

        protected override void WndProc(ref Message m)
        {
            switch(m.Msg)
            {
                case c_WmNcHitTest:
                    if(MouseTransparent && !DesignMode)
                    {
                        m.Result = (IntPtr)c_HtTransparent;
                        return;
                    }
                    break;

                case 0x0014: return;
            }
            base.WndProc(ref m);


            //if(MouseTransparent && m.Msg == c_WmNcHitTest && !DesignMode)
            //    m.Result = (IntPtr)c_HtTransparent;
            //else
            //    base.WndProc(ref m);
        }

        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            var w = f_Pen.Width / 2;
            Rect = new RectangleF(
                ClientRectangle.Location.Add(w, w),
                ClientRectangle.Size.Substract(2 * w, 2 * w));
            //Update();
        }

        protected override void OnPaint(PaintEventArgs pe)
        {
            pe.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(0, Color.Black)), ClientRectangle);
            Draw(pe.Graphics);
            base.OnPaint(pe);
        }

        //protected override void OnPaintBackground(PaintEventArgs e)
        //{
        //    if(BackColor != Color.Transparent)
        //        base.OnPaintBackground(e);
        //}

        protected override void OnMove(EventArgs e)
        {
            if(Parent != null) Parent.Invalidate(Bounds, true);
            //Update();
        }

        /* ------------------------------------------------------------------------------------------ */

        protected void Draw(Graphics graphics)
        {
            var lv_Opaque = (byte)(f_Opaque * 255);

            var lv_SmoothingMode = f_SmoothingMode;
            if(f_SmoothingMode != SmoothingMode.Default)
            {
                graphics.SmoothingMode = f_SmoothingMode;
            }

            graphics.DrawString(lv_Opaque.ToString(), Font, Brushes.Black, PointF.Empty);

            if(f_Pen != null)
                graphics.DrawEllipse(f_Pen, f_Rect);

            var lv_FeelBrush = f_FeelBrush
                ?? new SolidBrush(Color.FromArgb(lv_Opaque, BackColor));

            //if(f_FeelBrush != null)
            //graphics.FillEllipse(lv_FeelBrush, f_Rect);

            graphics.SmoothingMode = lv_SmoothingMode;
        }

        /* ------------------------------------------------------------------------------------------ */
    }
}
